import sys
import geopandas as gpd
from PyQt5.QtWidgets import QApplication, QMainWindow, QVBoxLayout
from qt_04VectorView_ui import Ui_VectorDataViewer
from PyQt5.QtWidgets import QFileDialog
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.figure import Figure
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker


class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.ui = Ui_VectorDataViewer()
        self.ui.setupUi(self)
        # 连接按钮的点击信号到对应的槽函数（自定义的打开文件函数）
        self.ui.open_vector_button.clicked.connect(self.open_vector_data)

        # 初始化可视化布局，避免首次打开时无布局问题
        self.init_visualization_layout()

    def open_vector_data(self):
        file_path, _ = QFileDialog.getOpenFileName(self, "选择矢量数据文件", "", "Shapefile (*.shp);;GeoJSON (*.geojson)")
        if file_path:
            try:
                data = gpd.read_file(file_path)
                self.ui.info_label.setText(f'成功打开矢量数据，包含 {len(data)} 条记录。')
                self.ui.path_line_edit.setText(file_path)
                # 清除之前的可视化内容
                self.clear_visualization()
                # 使用gpd.plot绘制矢量数据，获取Figure对象
                fig = self.plot_vector_data(data)
                # 创建FigureCanvas对象用于嵌入到Qt界面
                self.canvas = FigureCanvas(fig)
                # 设置可视化展示区域的布局并添加FigureCanvas
                self.setup_visualization_layout()
            except Exception as e:
                self.ui.info_label.setText(f'打开文件出现错误: {str(e)}')
        else:
            self.ui.info_label.setText('未选择任何文件。')

    def clear_visualization(self):
        """
        彻底清除之前的可视化相关内容，包括FigureCanvas及所在布局中的所有部件等
        """
        if hasattr(self, 'canvas'):
            layout = self.ui.visualization_widget.layout()
            if layout is not None:
                layout.removeWidget(self.canvas)
            self.canvas.deleteLater()
            del self.canvas
            # 仅移除布局中的子部件，不删除布局本身，避免布局丢失
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()

    def plot_vector_data(self, data):
        """
        使用gpd.plot绘制矢量数据并返回Figure对象，同时优化坐标轴刻度显示
        """
        fig = Figure(figsize=(6, 4))
        ax = fig.add_subplot(111)
        ax.clear()  # 清除坐标轴原有内容
        plt.clf()    # 清除Figure原有内容

        data.plot(ax=ax)

        # 优化x轴（经度相关或其他对应横坐标）刻度显示
        ax.xaxis.set_major_locator(ticker.AutoLocator())  # 自动选择合适的刻度位置
        ax.xaxis.set_major_formatter(ticker.ScalarFormatter(useOffset=False))  # 以简洁格式显示刻度值，不使用偏移量格式
        ax.tick_params(axis='x', which='major', pad=5)  # 增加x轴刻度标签与坐标轴的间距，避免遮挡，可调整数值
        # ax.yaxis.set_major_formatter(ticker.FormatStrFormatter('%.2f'))
        for tick in ax.get_xticklabels():
            tick.set_rotation(20)  # 旋转刻度标签，避免重叠，角度可调整
        # 优化y轴（纬度相关或其他对应纵坐标）刻度显示
        ax.yaxis.set_major_locator(ticker.AutoLocator())
        ax.yaxis.set_major_formatter(ticker.ScalarFormatter(useOffset=False))
        ax.tick_params(axis='y', which='major', pad=8)  # 增加y轴刻度标签与坐标轴的间距

        return fig

    def setup_visualization_layout(self):
        """
        设置可视化展示区域的布局，添加FigureCanvas并更新界面显示
        """
        visualization_widget = self.ui.visualization_widget
        layout = visualization_widget.layout()
        if layout is None:
            layout = QVBoxLayout(visualization_widget)
            layout.setContentsMargins(0, 0, 0, 0)
        else:
            # 如果布局已存在，先清空布局中的已有部件（避免重复添加）
            while layout.count():
                item = layout.takeAt(0)
                widget = item.widget()
                if widget is not None:
                    widget.deleteLater()
        layout.addWidget(self.canvas)
        visualization_widget.setLayout(layout)  # 设置布局到可视化组件
        visualization_widget.update()  # 更新可视化组件显示
        self.update()  # 更新整个窗口显示

    def init_visualization_layout(self):
        """
        初始化可视化展示区域的布局，避免首次打开时无布局情况
        """
        visualization_widget = self.ui.visualization_widget
        layout = visualization_widget.layout()
        if layout is None:
            layout = QVBoxLayout(visualization_widget)
            layout.setContentsMargins(0, 0, 0, 0)
            visualization_widget.setLayout(layout)


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainWindow()
    window.show()
    sys.exit(app.exec_())